//
//  KlineViewModel.swift
//  Exchange
//
//  Created by rui on 2018/4/28.
//  Copyright © 2018年 common. All rights reserved.
//

import UIKit

@objc protocol KlineViewModelDelegate: class {
    func socketChartDataChange(isTimeLine: Bool)
    func socketTickDataChange()
    func socketDataError()
    @objc optional func socketDepthDataChange(askPrice: Double, bidPrice: Double)
}



class KlineViewModel:BaseViewModel {
    
    var kPeriodPools: [String:Int] = {
        return  [kText("分时"):1,"1\(kText("分"))":1,"5\(kText("分"))":5,"15\(kText("分"))":15,"30\(kText("分"))":30,"1\(kText("小时"))":60,"4\(kText("小时"))":240,kText("日线"): 1 * 24 * 60,kText("周线"):7*24*60,kText("月线"):30*24*60]
    }()
    
    var coinModel: MarketCoinModel  =  MarketCoinModel()
    
    var serverChart = ServerChart()
    var serverTick  = ServerTick()
    
    var peroid: String = ""
    
    var dataArray = [[Double]]()
    
    weak var delegate: KlineViewModelDelegate?
    
    
    var symbolName: String {
        var name = coinModel.name.replacingOccurrences(of: "/", with: "_")
        name = name.count > 0 ? name : ""
        return name
    }
    
    func loadData() {
        SocketManager.shared.delegate = self
        if symbolName.count == 0 {
            return
        }
        serverTick.symbols = [symbolName]
        serverChart.symbol = symbolName
        SocketManager.shared.subscribe(server: serverTick)
    }
    
    func request(title: String) {
        if self.peroid == title {
            self.delegate?.socketDataError()
            return
        }
        self.peroid = title
        guard let period = kPeriodPools[title] else {
            dPrint("没有\(title)周期线")
             self.delegate?.socketDataError()
            return
        }
        serverChart.period = period
        SocketManager.shared.subscribe(server: serverChart)
    }
    
    func clean() {
        SocketManager.shared.cancelSubscribe(server: serverTick)
    }
    
}

extension KlineViewModel : SocketManagerDelegate {
    
    func socket(didReadTick data: [String : Any]) {
        dPrint(data)
    
        var data = data
        let cmd = data["cmd"] as? String ?? ""
        if cmd == "ticks" {
            if let symbols = data["symbols"] as? [String],let datas = data["datas"] as? [[String:Any]] {
                if let index = symbols.index(of: symbolName) {
                   let tickData =  datas[index]
                    data["symbol"] = symbolName
                    data["data"] = tickData
                    dPrint(data)
                }
            }
        }
        
        guard let tickData = data["data"] as? [String:Any],let symbol = data["symbol"] as? String else  { return }

        if symbol != symbolName {
            return
        }
        
        let open = tickData["day_open"] as? Double ?? 0
        let vol = tickData["day_volume"] as? Double ?? 0
        let price = tickData["price"] as? Double ?? 0
        let ts = tickData["ts"] as? Double ?? 0
        let amount = tickData["amount"] as? Double ?? 0
        let low = tickData["day_low"] as? Double ?? 0
        let high = tickData["day_high"] as? Double ?? 0
        
        let strs = symbolName.components(separatedBy: "_")
        let money = Double(CYCalculate.cy_multiplying(firstNumber: AppContext.default.getExTick(symbol: strs.last ?? ""), lastNumber:price, digit: 8))!
     
        coinModel.amount = amount
        coinModel.open = open
        coinModel.price = price
        coinModel.ts = ts
        coinModel.vol = vol
        coinModel.money = money
        coinModel.low = low
        coinModel.high = high
        
        
        if self.dataArray.isEmpty {
            self.delegate?.socketTickDataChange()
            return
        }
        
        
        let preData = self.dataArray.last!
        var result = ComparisonResult.orderedSame
        var curTime: TimeInterval = 0
        if self.peroid == kText("月线") {
            let c = Calendar.current
            let curDate = Date(timeIntervalSince1970: ts / 1000)
            let dateFormat = DateFormatter()
            dateFormat.dateFormat = "yyyy-MM"
            let str = dateFormat.string(from: curDate)
            let curD = dateFormat.date(from: str)
            curTime = curD!.timeIntervalSince1970
            let set: Set = [Calendar.Component.year,.month]
            let preComps = c.dateComponents(set, from: Date(timeIntervalSince1970: preData[5]))
            let curComps = c.dateComponents(set, from: curDate)
            if preComps.year == curComps.year,preComps.month == curComps.month {
                result = .orderedSame
            }else {
                result = .orderedAscending
            }
            
        }else {
            var currentTime = Int(ts)
            let preTime = Int(preData[5] * 1000)
            let deltT = currentTime - preTime
            guard let period = kPeriodPools[self.peroid] else {
                return
            }
            let unit = period * 60 * 1000
            currentTime += -(deltT % unit)
            if preTime == currentTime {
                result = .orderedSame
            }else if currentTime > preTime  {
                result = .orderedAscending
            }else {
                result = .orderedDescending
            }
            curTime = TimeInterval(currentTime / 1000)
        }
        
        var last =  [Double]()
        if result == .orderedSame {
            last = self.dataArray.removeLast()
            last[1] = price
            last[2] = max(last[2], price)
            last[3] = min(last[3], price)
            last[4] = last[4] + amount
            last[5] = curTime
        }else if result == .orderedAscending {
            last.append(price)
            last.append(price)
            last.append(price)
            last.append(price)
            last.append(amount)
            last.append(curTime)
        }
        if last.count > 0 {
            self.dataArray.append(last)
        }
        self.delegate?.socketTickDataChange()
    }
    
    func socket(didReadChart data: [String : Any]) {

        guard var klineData = data["data"] as? [[Double]], let symbol = data["symbol"] as? String, symbol == symbolName else  { return }
        klineData.reverse()
        var isTimeLine = false
        if let per = data["period"] as? Int,per == 1,self.peroid == kText("分时") {
           isTimeLine = true
        }
        self.dataArray = klineData
        self.delegate?.socketChartDataChange(isTimeLine: isTimeLine)
    }
    
    func socketError() {
        self.delegate?.socketDataError()
    }
}
